package automatica.datamining;

import static constants.GTextbookConstants.language;

import java.util.Vector;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JPanel;

import automatica.GSI;
import automatica.Type;
import automatica.Utility;

import ui.view.NodeInfo;

public class RelationMining {


	private Vector<String> newObjects = new Vector<String>(1,1);
	private Vector<RelationTriple> existObjects = new Vector<RelationTriple>(1,1);
	
	public void setExistObjects(Vector<RelationTriple> existObjects) {
		this.existObjects = existObjects;
	}

	public Vector<String> getNewObjects() {
		return newObjects;
	}


	public void setNewObjects(Vector<String> newObjects) {
		this.newObjects = newObjects;
	}


	public Vector<RelationTriple> getExistObjects() {
		return existObjects;
	}

	
	public RelationMining(Vector<RelationTriple> existObjects,Vector<String> newObjects){
		this.existObjects = existObjects;
		this.newObjects = newObjects;
	}
	
	
	public RelationMining(){
		
	}

	public RelationMining(String data, String dataType, String relationType, NodeInfo current, int language){
		//check which relations should be checked
		
		
		
		if(relationType.equals("contextOf")){
			
			existObjects = contextMining(data, dataType, current, language)[0];
			newObjects = contextMining(data, dataType, current, language)[1];

		}
		
		if(relationType.equals("inherit")){
			existObjects = inheritanceMining(data, dataType, current, language);
		}
		
		if(relationType.equals("Derive")){
			
		}
		
		if(relationType.equals("Imply")){
			
		}
		
		if(relationType.equals("Introduce")){
			
		}
		
		if(relationType.equals("Remark")){
			
		}
		
		if(relationType.equals("Complicate")){
			
		}
		
		deleteDuplicate();
		
	}
	
	
	
	/**
	 * contextOf relation: pre --> sub
	 * @param data
	 * @param dataType
	 * @param current
	 * @param language
	 * @return
	 */
	
	public Vector[] contextMining(String data, String dataType, NodeInfo current, int language){
		Vector<RelationTriple> relations = new Vector<RelationTriple>(1,1);
		Vector<String> newObjects = new Vector<String>(1,1);
		if(dataType.indexOf("String")!=-1 && dataType.indexOf("Formal")!=-1 && dataType.indexOf("Definition")!=-1){
			int index = data.indexOf("\u225D");
			
			String instance = data.substring(0,index);
			String defBody = data.substring(index+1,data.length());
			
			
			GSI gsi = new GSI(instance,dataType).union(new GSI(defBody,dataType));
			gsi.print();
			
			//contextMining instance
			if(Utility.isMathematicalFormula(instance)){
				if(Utility.isPolishFormula(instance)){
					Vector<String> termSet = Utility.generateTermSet(instance);
					for(int i = 1; i < termSet.size(); i++){
						Vector[] sub = contextMiningOfClause(termSet.get(i),dataType,gsi,current,language);
						for(int j = 0 ; j < sub[0].size(); j++){
							relations.add((RelationTriple)(sub[0].get(j)));
						}
						for(int k = 0; k < sub[1].size(); k++){
							newObjects.add((String)(sub[1].get(k)));
						}
					}
				}
			}
			
			//contextMining return object
			if(defBody!=null&&defBody.trim().length()!=0){
				Vector<String> binding = Utility.splitAllList(defBody);
				for(int i = 0; i < binding.size(); i++){
					Vector<String> oc = Utility.splitBinding(binding.get(i));
					String fatherInstance = oc.get(0);
					/*
					Vector[] fiSub = contextMiningOfClause(fatherInstance,dataType,gsi,current,language);
					for(int j = 0 ; j < fiSub[0].size(); j++){
						relations.add((RelationTriple)(fiSub[0].get(j)));
					}
					for(int k = 0; k < fiSub[1].size(); k++){
						newObjects.add((String)(fiSub[1].get(k)));
					}*/
					Vector<String> fi = Utility.splitConstraint(fatherInstance);
					for(int t = 0; t < fi.size(); t++){
						Vector[] fiSub = contextMiningOfClause(fi.get(t),dataType,gsi,current,language);
						for(int j = 0 ; j < fiSub[0].size(); j++){
							relations.add((RelationTriple)(fiSub[0].get(j)));
						}
						for(int k = 0; k < fiSub[1].size(); k++){
							newObjects.add((String)(fiSub[1].get(k)));
						}
					}
					if(oc.size()>1){
						String constraint = oc.get(1);
						Vector<String> constraints = Utility.splitConstraint(constraint);
						for(int t = 0; t < constraints.size(); t++){
							Vector[] cssub = contextMiningOfClause(constraints.get(t),dataType,gsi,current,language);
							for(int j = 0 ; j < cssub[0].size(); j++){
								relations.add((RelationTriple)(cssub[0].get(j)));
							}
							for(int k = 0; k < cssub[1].size(); k++){
								newObjects.add((String)(cssub[1].get(k)));
							}
						}
					}
					
					
				}

			}
			
		}else if(dataType.indexOf("String")!=-1 && dataType.indexOf("Formal")!=-1 && dataType.indexOf("Assertion")!=-1){
			String hypothesis = null;
			String conclusion = null;
			
			int index = data.indexOf("<=>");
			if(index!=-1){
				hypothesis = data.substring(0,index);
				conclusion = data.substring(index+3,data.length());
			}else{
				index = data.indexOf("=>");
				if(index!=-1){
					hypothesis = data.substring(0,index);
					conclusion = data.substring(index+2,data.length());
				}
			}
			
			GSI gsi = new GSI(hypothesis,dataType);
			gsi.print();

			
			Vector<String> hypoClauses = Utility.splitAllList("{"+hypothesis+"}");
			Vector<String> ConclusionClauses = Utility.splitAllList("{"+conclusion+"}");

			
			for(int i =0; i < hypoClauses.size(); i++){
				System.out.println("**************"+hypoClauses.get(i)+"*******************");
				Vector[] sub = contextMiningOfClause(hypoClauses.get(i),dataType,gsi,current,language);
				for(int j = 0 ; j < sub[0].size(); j++){
					relations.add((RelationTriple)(sub[0].get(j)));
				}
				for(int k = 0; k < sub[1].size(); k++){
					newObjects.add((String)(sub[1].get(k)));
				}
			}
			

			for(int i =0; i < ConclusionClauses.size(); i++){
				Vector[] sub = contextMiningOfClause(ConclusionClauses.get(i),dataType,gsi,current,language);
				for(int j = 0 ; j < sub[0].size(); j++){
					relations.add((RelationTriple)(sub[0].get(j)));
				}
				for(int k = 0; k < sub[1].size(); k++){
					newObjects.add((String)(sub[1].get(k)));
				}
			}

			
		}

		Vector[] result={relations,newObjects};
		
		return result;

	}
	
	public Vector[] contextMiningOfClause(String clause, String dataType, GSI gsi, NodeInfo current, int language){
		Vector<RelationTriple> relations = new Vector<RelationTriple>(1,1);
		Vector<String> newObjects = new Vector<String>(1,1);
		if(dataType.indexOf("String")!=-1 && dataType.indexOf("Formal")!=-1){

			if(Utility.isMathematicalFormula(clause)){
				if(Utility.isPolishFormula(clause)){
					Vector<NodeInfo> pres = Utility.fetchDefinitionFromKB(clause,gsi,language);
					if(pres.size()>0){
						for(int i = 0; i < pres.size(); i++){
							if(pres.get(i)!=null){
								relations.add(new RelationTriple(pres.get(i),current,"contextOf"));
							}
						}
					}else{
						newObjects.add(new Type(clause,gsi).getValue());
					}
				
					//get the children
					Vector<String> termSet = Utility.generateTermSet(clause);
				
					for(int i = 1; i < termSet.size(); i++){
						Vector[] children = contextMiningOfClause(termSet.get(i),dataType,gsi,current,language);
						for(int j = 0 ; j < children[0].size(); j++){
							relations.add((RelationTriple)(children[0].get(j)));
						}
						for(int k = 0; k < children[1].size(); k++){
							newObjects.add((String)(children[1].get(k)));
						}
					}
				}
			}else if(Utility.isReference(clause)){
				String[] reference = Utility.generateReferenceSet(clause);
				Vector[] c = contextMiningOfClause(reference[1],dataType,gsi,current,language);
				relations = c[0];
				newObjects = c[1];
			}
			

		}

		Vector[] result={relations,newObjects};
		
		return result;

	}
	
	/**
	 * inheritance relation: child --> father
	 * @param data
	 * @param dataType
	 * @param current
	 * @param language
	 * @return
	 */
	
	public Vector<RelationTriple> inheritanceMining(String data, String dataType, NodeInfo current, int language){
		Vector<RelationTriple> result = new Vector<RelationTriple>(1,1);

		if(dataType.indexOf("String")!=-1 && dataType.indexOf("Formal")!=-1 && dataType.indexOf("Definition")!=-1){
			//parse the data
			int index = data.indexOf("\u225D");
			
			String instance = data.substring(0,index);
			String defBody = data.substring(index+1,data.length());
			
			
			GSI gsi = new GSI(instance,dataType).union(new GSI(defBody,dataType));
			gsi.print();
			
			Vector<NodeInfo> fatherNodes = Utility.getFatherNodesOfDefbody(defBody, gsi, dataType); 
			

			
			for(int i = 0; i < fatherNodes.size(); i++){
				if(fatherNodes.get(i)!=null){
					result.add(new RelationTriple(current,fatherNodes.get(i),"inherit"));
				}
			}
		}

		
		return result;

	}

	
	
	public RelationMining union(RelationMining rm){
		if(rm.getExistObjects()!=null){
			for(int i = 0; i < rm.getExistObjects().size(); i++){
				this.existObjects.add(rm.getExistObjects().get(i));
			}
		}
		if(rm.getNewObjects()!=null){
			for(int i = 0; i < rm.getNewObjects().size(); i++){
				this.newObjects.add(rm.getNewObjects().get(i));
			}
		}
		return this;
	}
	
	
	public void deleteDuplicate(){
		Vector<RelationTriple> newExistObjects = new Vector<RelationTriple>(1,1);
		Vector<String> newObjects = new Vector<String>(1,1);
		for(int i = 0; i < this.getExistObjects().size(); i++){
			boolean pick = true;
			RelationTriple current = this.getExistObjects().get(i);
			if(newExistObjects.size()==0){
				newExistObjects.add(current);
			}else{
				for(int j =0; j < newExistObjects.size(); j++){
					if(current.toString().equals(newExistObjects.get(j).toString())){
						pick = false;
					}
				}
				if(pick == true){
					newExistObjects.add(current);
				}
			}
		}
		for(int i = 0; i < this.getNewObjects().size(); i++){
			boolean pick = true;
			String current = this.getNewObjects().get(i);
			if(newObjects.size()==0){
				newObjects.add(current);
			}else{
				for(int j =0; j < newObjects.size(); j++){
					if(current.toString().equals(newObjects.get(j).toString())){
						pick = false;
					}
				}
				if(pick == true){
					newObjects.add(current);
				}
			}
		}
		
		this.setExistObjects(newExistObjects);
		this.setNewObjects(newObjects);
	}
	
	
	
	public class RelationTriple{
		private NodeInfo precursor;
		private NodeInfo subsequence;
		private String relationType;
		
		public RelationTriple(NodeInfo pre, NodeInfo sub, String relation){
			this.precursor = pre;
			this.subsequence = sub;
			this.relationType = relation;
		}
		
		public String toString(){
			return "["+precursor.getAuthor() + "] " + precursor.toStringWithVersion() + "  \u21E8" + relationType + "\u21E8  " + "["+precursor.getAuthor() + "] " + subsequence.toStringWithVersion();
		}

		public NodeInfo getPrecursor() {
			return precursor;
		}

		public void setPrecursor(NodeInfo precursor) {
			this.precursor = precursor;
		}

		public NodeInfo getSubsequence() {
			return subsequence;
		}

		public void setSubsequence(NodeInfo subsequence) {
			this.subsequence = subsequence;
		}

		public String getRelationType() {
			return relationType;
		}

		public void setRelationType(String relationType) {
			this.relationType = relationType;
		}

	}
	
 
}
